<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .box {
            position: relative;
        }
    </style>
</head>
<body>
<div class="box"></div>
<script type="module">
    import { images } from './images.js'
    const IMAGE_WIDTH = 300;
    const box = document.querySelector(".box");
    let columnCount = 0;
    let oldObj = null;

    function getColumnCount(boxWidth) {
        let count = 0;
        let width = 0;
        while (true) {
            if (width + IMAGE_WIDTH + 20 <= boxWidth) {
                count++;
                width += IMAGE_WIDTH + 20;
            } else if (width + IMAGE_WIDTH <= boxWidth) {
                count++;
                break;
            } else {
                break;
            }
        }

        return count;
    }

    function run() {
        const boxWidth = box.clientWidth;
        const _columnCount = getColumnCount(boxWidth);
        if (_columnCount === columnCount) {
            return;
        } else {
            columnCount = _columnCount;
        }
        const obj = {};

        for (let i = 0; i < columnCount; i++) {
            obj[i] = {
                key: i,
                totalHeight: 0,
                arr: []
            };
        }

        function getColumnObj() {
            const keys = Object.keys(obj);
            return keys.slice(1).reduce((columnObj, key) => {
                const acc = obj[key];
                if (columnObj.totalHeight > acc.totalHeight) {
                    return acc;
                } else {
                    return  columnObj;
                }
            }, obj[keys[0]])
        }

        function findImg(url) {
            if (oldObj === null) return null;
            const keys = Object.keys(oldObj);
            for (const key of keys) {
                for (const item of oldObj[key].arr) {
                    if (item.url === url) {
                        return item;
                    }
                }
            }

            return  null;
        }

        async function loadImage(url) {
            const oldImg = findImg(url)?.img;

            if (oldImg == null) {
                const img = new Image();
                img.src = url;

                img.onload = function () {
                    const radio = img.naturalWidth / img.naturalHeight;
                    const height = IMAGE_WIDTH / radio;

                    img.width = IMAGE_WIDTH;
                    img.height = height;

                    const columnObj = getColumnObj();

                    Object.assign(img.style, {
                        position: 'absolute',
                        transition: "all 0.3s",
                        top: columnObj.totalHeight + 'px',
                        left: columnObj.key * IMAGE_WIDTH + (columnObj.key - 1) * 20 + 'px',
                    })

                    const item = {
                        url,
                        img,
                        top: columnObj.totalHeight,
                        left: columnObj.key * IMAGE_WIDTH + (columnCount - 1) * 20,
                    }

                    columnObj.totalHeight += height + 20;
                    columnObj.arr.push(item);


                    box.append(img);

                    // box.style.height = columnObj.totalHeight + "px";
                }
            } else {
                const columnObj = getColumnObj();

                Object.assign(oldImg.style, {
                    top: columnObj.totalHeight + 'px',
                    left: columnObj.key * IMAGE_WIDTH + (columnObj.key - 1) * 20 + 'px',
                })

                const item = {
                    url,
                    img: oldImg,
                    top: columnObj.totalHeight,
                    left: columnObj.key * IMAGE_WIDTH + (columnCount - 1) * 20,
                }

                columnObj.totalHeight += oldImg.height + 20;
                columnObj.arr.push(item);
            }
        }

        async function load() {
            for (const url of images) {
                await loadImage(url);
            }
        }

        load().then(() => {
            oldObj = obj;
        });
    }

    run();

    function debounce(fn, timeout = 0) {
        let id;

        return () => {
            if (id) {
                clearTimeout(id);
            }
            id =setTimeout(fn, timeout)
        }
    }

    const fn = debounce(run, 100)

    window.addEventListener('resize', fn)

</script>
</body>
</html>